package com.aischool.common;

import java.lang.annotation.Annotation;
import java.util.List;

import com.aischool.common.ClassScaner;
import com.aischool.common.kit.Md5Kit;
import com.aischool.common.model._MappingKit;
import com.aischool.interceptor.PermissionInterceptor;
import com.aischool.utils.ArrayUtil;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.core.Controller;
import com.jfinal.json.FastJsonFactory;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.dialect.PostgreSqlDialect;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.plugin.ehcache.EhCachePlugin;
import com.jfinal.server.undertow.UndertowServer;
import com.jfinal.template.Engine;
import com.jfinal.weixin.sdk.api.ApiConfig;
import com.jfinal.weixin.sdk.api.ApiConfigKit;
import com.jfinal.wxaapp.WxaConfig;
import com.jfinal.wxaapp.WxaConfigKit;

/**
 * 本 demo 仅表达最为粗浅的 jfinal 用法，更为有价值的实用的企业级用法
 * 详见 JFinal 俱乐部: http://jfinal.com/club
 * 
 * API 引导式配置
 */
public class AppConfig extends JFinalConfig {
	
	static Prop p;
	
	/**
	 * 启动入口，运行此 main 方法可以启动项目，此 main 方法可以放置在任意的 Class 类定义中，不一定要放于此
	 */
	public static void main(String[] args) {
//		String md5pwd = Md5Kit.MD5For8("123456"); 
//		System.out.println(md5pwd);
		UndertowServer.start(AppConfig.class);
	}
	
	/**
	 * 先加载开发环境配置，然后尝试加载生产环境配置，生产环境配置不存在时不会抛异常
	 * 在生产环境部署时后动创建 demo-config-pro.txt，添加的配置项可以覆盖掉
	 * demo-config-dev.txt 中的配置项
	 */
	static void loadConfig() {
		if (p == null) {
			// 优先加载生产环境配置文件
			p = PropKit.useFirstFound("config-pro.txt", "config-dev.txt");
		}
	}
	
	/**
	 * 配置常量
	 */
	public void configConstant(Constants me) {
		loadConfig();
		
		me.setDevMode(p.getBoolean("devMode", false));
		
		// 支持 Controller、Interceptor 之中使用 @Inject 注入业务层，并且自动实现 AOP
		me.setInjectDependency(true);
		
		/** 配置页面 */
		/** 编码配置 */
		me.setEncoding("UTF-8");
		/** 上传文件目录 */
		me.setBaseUploadPath("upload");
		/** 设置参数分隔符 */
		me.setUrlParaSeparator("-");
		/** 设置JSON */
		me.setJsonFactory(new FastJsonFactory());
		me.setJsonDatePattern("yyyy-MM-dd HH:mm:ss");
		/** 设置log4j **/
		
		// ApiConfigKit 设为开发模式可以在开发阶段输出请求交互的 xml 与 json 数据
        ApiConfigKit.setDevMode(me.getDevMode());
	}
	
	/**
	 * 配置路由
	 */
	public void configRoute(Routes me) {
		Log.getLog(this.getClass()).debug("config route");
		
        //System.out.println("config route");
		
        me.setMappingSuperClass(true);

		List<Class<Controller>> controllerClassList = ClassScaner.scanSubClass(Controller.class);
        if (ArrayUtil.isNotEmpty(controllerClassList)) {
            //System.out.println("controllerClassList");
            for (Class<Controller> clazz : controllerClassList) {
                //System.out.println("clazz:"+clazz.getAnnotations());
            	Annotation[] annotations = clazz.getAnnotations();
                for(int i=0;i<annotations.length;i++) {
                	if ("com.aischool.routes.RouteMapping".equals(annotations[i].annotationType().getName())) {
                    	//System.out.println(((com.aischool.routes.RouteMapping)annotations[i]).url());
                    	me.add(((com.aischool.routes.RouteMapping)annotations[i]).url(), clazz);
                	}
                }
            }
        }
        
        //me.setBaseViewPath("/WEB-INF/views");
        
	}
	
	public void configEngine(Engine me) {
		me.setDevMode(true);
//		me.addSharedFunction("/common/_layout.html");
//		me.addSharedFunction("/common/_paginate.html");
	}
	
	/**
	 * 配置插件
	 */
	public void configPlugin(Plugins me) {
		// 配置 druid 数据库连接池插件
		DruidPlugin druidPlugin = new DruidPlugin(p.get("jdbc.url"), p.get("jdbc.username"), p.get("jdbc.password"), p.get("jdbc.driver"));
       
		// 配置ActiveRecord插件
		ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
		arp.setDialect(new PostgreSqlDialect());  
		arp.setShowSql(true);
		// 所有映射在 MappingKit 中自动化搞定
		_MappingKit.mapping(arp);
		me.add(druidPlugin);
		me.add(arp);
		
		//** 缓存 */
		me.add(new EhCachePlugin()); 
	}
	
	public static DruidPlugin createDruidPlugin() {
		loadConfig();
		
		return new DruidPlugin(p.get("jdbc.url"), p.get("jdbc.username"), p.get("jdbc.password"), p.get("jdbc.driver"));
	}
	
	/**
	 * 配置全局拦截器
	 */
	public void configInterceptor(Interceptors me) {
		me.addGlobalActionInterceptor(new PermissionInterceptor());
	}
	
	/**
	 * 配置处理器
	 */
	public void configHandler(Handlers me) {
		
	}
	
	public void afterJFinalStart() {
        // 1.5 之后支持redis存储access_token、js_ticket，需要先启动RedisPlugin
//        ApiConfigKit.setAccessTokenCache(new RedisAccessTokenCache());
        // 1.6新增的2种初始化
//        ApiConfigKit.setAccessTokenCache(new RedisAccessTokenCache(Redis.use("weixin")));
//        ApiConfigKit.setAccessTokenCache(new RedisAccessTokenCache("weixin"));

        ApiConfig ac = new ApiConfig();
        // 配置微信 API 相关参数
        ac.setToken(PropKit.get("token"));
        ac.setAppId(PropKit.get("appId"));
        ac.setAppSecret(PropKit.get("appSecret"));

        /**
         *  是否对消息进行加密，对应于微信平台的消息加解密方式：
         *  1：true进行加密且必须配置 encodingAesKey
         *  2：false采用明文模式，同时也支持混合模式
         */
        ac.setEncryptMessage(PropKit.getBoolean("encryptMessage", false));
        ac.setEncodingAesKey(PropKit.get("encodingAesKey", "setting it in config file"));

        /**
         * 多个公众号时，重复调用ApiConfigKit.putApiConfig(ac)依次添加即可，第一个添加的是默认。
         */
        ApiConfigKit.putApiConfig(ac);

        /**
         * 1.9 新增LocalTestTokenCache用于本地和线上同时使用一套appId时避免本地将线上AccessToken冲掉
         *
         * 设计初衷：https://www.oschina.net/question/2702126_2237352
         *
         * 注意：
         * 1. 上线时应保证此处isLocalDev为false，或者注释掉该不分代码！
         *
         * 2. 为了安全起见，此处可以自己添加密钥之类的参数，例如：
         * http://localhost/weixin/api/getToken?secret=xxxx
         * 然后在WeixinApiController#getToken()方法中判断secret
         *
         * @see WeixinApiController#getToken()
         */
//        if (isLocalDev) {
//            String onLineTokenUrl = "http://localhost/weixin/api/getToken";
//            ApiConfigKit.setAccessTokenCache(new LocalTestTokenCache(onLineTokenUrl));
//        }
        WxaConfig wc = new WxaConfig();
        wc.setAppId("wx4f53594f9a6b3dcb");
        wc.setAppSecret("eec6482ba3804df05bd10895bace0579");
        WxaConfigKit.setWxaConfig(wc);
    }

}
